package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.DeptDto;
import com.zzyl.dto.PostDto;
import com.zzyl.enmus.PostStatus;
import com.zzyl.entity.Dept;
import com.zzyl.entity.Post;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeptMapper;
import com.zzyl.mapper.PostMapper;
import com.zzyl.service.DeptService;
import com.zzyl.service.PostService;
import com.zzyl.utils.BeanConv;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.DeptVo;
import com.zzyl.vo.PostVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 岗位表服务实现类
 */
@Service
public class PostServiceImpl implements PostService {

    @Autowired
    PostMapper postMapper;

    @Autowired
    DeptService deptService;

    @Autowired
    DeptMapper deptMapper;

    /**
     * 多条件查询岗位表分页列表
     *
     * @param postDto  查询条件
     * @param pageNum  页码
     * @param pageSize 每页条数
     * @return Page<PostVo>
     */
    @Override
    public PageResponse<PostVo> findPostPage(PostDto postDto, int pageNum, int pageSize) {
        // 通过 PageHelper.startPage() 方法，设置当前页码和每页的记录数
        PageHelper.startPage(pageNum, pageSize);

        // 岗位必须关联一个部门，因此如果部门编号为空，直接抛出异常
        if (EmptyUtil.isNullOrEmpty(postDto.getDeptNo())) {
            throw new BaseException("部门不能为空");
        }

        // 查询岗位数据，返回分页结果
        // 查询结果被封装为 Page 对象，Page 是一个包含分页信息的集合类
        Page<List<Post>> page = postMapper.selectPage(postDto);

        // 将查询结果转换为统一的 PageResponse 对象（转换方法封装在 PageResponse 类中）
        PageResponse<PostVo> pageResponse = PageResponse.of(page, PostVo.class);

        // 如果分页查询结果不为空，则进行后续数据装配
        if (!EmptyUtil.isNullOrEmpty(pageResponse.getRecords())) {
            // 获取所有岗位对应的部门编号集合
            // 从分页结果中提取每个岗位的部门编号，形成一个集合
            List<String> deptNos = pageResponse.getRecords()
                    .stream()
                    .map(PostVo::getDeptNo)
                    .collect(Collectors.toList());

            // 根据部门编号集合查询部门详细信息
            List<DeptVo> deptVoList = deptService.findDeptInDeptNos(deptNos);

            // 遍历分页结果中的岗位记录，进行数据装配
            pageResponse.getRecords().forEach(n -> {
                // 将岗位的创建时间格式化为指定的日期格式字符串
                n.setCreateDay(LocalDateTimeUtil.format(n.getCreateTime(), "yyyy-MM-dd"));

                // 遍历查询到的部门信息，为每个岗位匹配其对应的部门信息
                deptVoList.forEach(d -> {
                    // 如果岗位的部门编号与部门的编号匹配，则装配部门信息
                    if (n.getDeptNo().equals(d.getDeptNo())) {
                        // 将部门信息从 DeptVo 转换为所需的格式，并设置到岗位中
                        n.setDeptVo(BeanConv.toBean(d, DeptVo.class));
                    }
                });
            });
        }

        // 返回封装好的分页结果
        return pageResponse;
    }

    /**
     * 新建岗位
     *
     * @param postDto 对象信息
     * @return PostDto
     */
    @Override
    public PostVo createPost(PostDto postDto) {
        // 将传入的 PostDto 转换为 Post 实体对象
        Post post = BeanUtil.toBean(postDto, Post.class);
        // 调用 createPostNo 方法生成岗位编号
        String postNo = createPostNo(post.getDeptNo());
        post.setPostNo(postNo);
        // 插入岗位数据到数据库
        int flag = postMapper.insert(post);
        // 部门编号和岗位名称有唯一约束，如果插入失败，抛出异常
        if (flag == 0) {
            throw new RuntimeException("保存职位信息出错");
        }
        // 转换 Post 对象为 PostVo 对象返回
        PostVo postVoResult = BeanConv.toBean(post, PostVo.class);
        // 装配部门信息
        DeptDto deptDto = DeptDto.builder()
                .dataState(SuperConstant.DATA_STATE_0) // 数据状态为正常
                .parentDeptNo(postDto.getDeptNo())    // 设置父部门编号
                .build();
        // 将部门信息装配到岗位对象中
        List<Dept> deptList = deptMapper.selectList(deptDto);
        if (!EmptyUtil.isNullOrEmpty(deptList)) {
            postVoResult.setDeptVo(BeanConv.toBean(deptList.get(0), DeptVo.class));
        }
        return postVoResult;
    }

    /**
     * 修改岗位
     *
     * @param postDto 对象信息
     * @return Boolean
     */
    @Override
    public Boolean updatePost(PostDto postDto) {
        // 转换PostVo为Post
        Post post = BeanUtil.toBean(postDto, Post.class);

        // 如果岗位状态为启用，检查是否已分配用户
        if (postDto.getDataState().equals(PostStatus.START.getOrdinal())) {
            String[] postIds = {post.getPostNo()};
            Integer total = checkPostHasUser(postIds);
            if (total > 0) {
                throw new BaseException("岗位已分配用户，不能禁用");
            }
        }
        // 更新岗位信息
        int flag = postMapper.updateByPrimaryKey(post);
        // 岗位名称必须唯一，如果更新失败，抛出异常
        if (flag == 0) {
            throw new RuntimeException("修改职位信息出错");
        }
        return true;
    }

    /**
     * 多条件查询岗位表列表
     *
     * @param postDto 查询条件
     * @return List<PostVo>
     */
    @Override
    public List<PostVo> findPostList(PostDto postDto) {

        postDto.setDataState(SuperConstant.DATA_STATE_0);
        List<Post> postList = postMapper.selectList(postDto);
        List<PostVo> postVoList = BeanConv.toBeanList(postList, PostVo.class);
        if (!EmptyUtil.isNullOrEmpty(postVoList)) {
            //对应部门
            List<String> deptNos = postVoList.stream().map(PostVo::getDeptNo).collect(Collectors.toList());
            List<DeptVo> deptVoList = deptService.findDeptInDeptNos(deptNos);
            postVoList.forEach(n -> {
                //装配部门
                deptVoList.forEach(d -> {
                    if (n.getDeptNo().equals(d.getDeptNo())) {
                        n.setDeptVo(BeanConv.toBean(d, DeptVo.class));
                    }
                });

            });
        }
        return postVoList;
    }

    @Override
    public List<PostVo> findPostVoListByUserId(Long userId) {

        return postMapper.findPostVoListByUserId(userId);
    }

    /**
     * 创建编号
     *
     * @param deptNo 部门编号
     * @return 岗位编号
     */
    private String createPostNo(String deptNo) {
        //查询当前部门下的所有下属节点
        PostDto postDto = PostDto.builder().deptNo(deptNo).build();
        List<Post> postList = postMapper.selectList(postDto);
        // 如果没有下属岗位，生成新编号
        if (EmptyUtil.isNullOrEmpty(postList)) {
            return NoProcessing.createNo(deptNo, false);
        } else {
            // 如果有下属岗位，取最大编号加 1
            Long postNo = postList.stream()
                    .map(post -> Long.valueOf(post.getPostNo()))
                    .max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(postNo), true);
        }
    }

    /**
     * 批量删除
     *
     * @param postIds 岗位编号数组
     * @return
     */
    @Override
    public int deletePostByIds(String[] postIds) {
        //验证当前岗位是否被用户关联
        Integer total = checkPostHasUser(postIds);
        if (total > 0) {
            throw new RuntimeException("岗位已分配,不能删除");
        }
        return postMapper.deletePostByIds(postIds);
    }

    /**
     * 校验岗位是否已分配用户
     *
     * @param postIds 岗位编号数组
     * @return 分配用户的总数
     */
    public Integer checkPostHasUser(String[] postIds) {
        return postMapper.checkPostHasUser(postIds);
    }
}
